#include "log_manager.h"
#include <fstream>
#include <sstream>
#include <iomanip>
#include <algorithm>

LogManager::LogManager() {
    last_archive_time_ = std::chrono::system_clock::now();
}

LogManager::~LogManager() {
    spdlog::drop_all(); // 确保所有日志器被正确清理
}

void LogManager::initialize() {
    // 创建必要的目录
    std::filesystem::create_directories("logs/archive");
    
    // 设置日志器
    setupLoggers();
    
    // 初始归档检查
    archiveAndClean();
}

void LogManager::setupLoggers() {
    // 系统日志器
    auto system_logger = spdlog::rotating_logger_mt("system", "logs/system.log", 
                                                   max_log_size_, max_log_files_);
    system_logger->set_level(spdlog::level::info);
    
    // 交易日志器
    auto trade_logger = spdlog::rotating_logger_mt("trade", "logs/trade.log",
                                                  max_log_size_, max_log_files_);
    trade_logger->set_level(spdlog::level::debug);
    
    // 错误日志器
    auto error_logger = spdlog::rotating_logger_mt("error", "logs/error.log",
                                                  max_log_size_, max_log_files_);
    error_logger->set_level(spdlog::level::err);
}

void LogManager::archiveAndClean() {
    auto now = std::chrono::system_clock::now();
    if (std::chrono::duration_cast<std::chrono::hours>(now - last_archive_time_).count() < 24) {
        return;
    }
    
    last_archive_time_ = now;
    
    try {
        // 创建日期格式的子目录
        std::time_t now_time = std::chrono::system_clock::to_time_t(now);
        std::tm tm = *std::localtime(&now_time);
        std::ostringstream oss;
        oss << std::put_time(&tm, "logs/archive/%Y-%m-%d");
        std::filesystem::create_directories(oss.str());
        
        // 归档日志文件
        for (const auto& entry : std::filesystem::directory_iterator("logs")) {
            if (entry.is_regular_file() && 
                entry.path().extension() == ".log" &&
                entry.path().filename() != "hft_system.log") {
                
                auto new_path = oss.str() + "/" + entry.path().filename().string();
                std::filesystem::rename(entry.path(), new_path);
                compressFile(new_path);
            }
        }
        
        spdlog::get("system")->info("日志归档完成: {}", oss.str());
    } catch (const std::exception& e) {
        spdlog::get("error")->error("日志归档失败: {}", e.what());
    }
    
    // 清理旧日志
    cleanOldLogs();
}

#include <zlib.h>
#include <vector>
#include <spdlog/sinks/syslog_sink.h>
#include <spdlog/async.h>
#include <regex>
#include <random>
#include <thread>

bool LogManager::compressFile(const std::filesystem::path& path) {
    auto start_time = std::chrono::high_resolution_clock::now();
    
    try {
        // 读取原始文件
        std::ifstream in(path, std::ios::binary);
        std::vector<char> buffer((std::istreambuf_iterator<char>(in)), 
                                std::istreambuf_iterator<char>());
        in.close();

        // 准备压缩缓冲区
        uLongf compressed_size = compressBound(buffer.size());
        std::vector<Bytef> compressed(compressed_size);

        // 执行压缩
        if (compress2(compressed.data(), &compressed_size,
                     reinterpret_cast<Bytef*>(buffer.data()), buffer.size(),
                     Z_BEST_COMPRESSION) != Z_OK) {
            throw std::runtime_error("压缩失败");
        }

        // 写入压缩文件
        std::ofstream out(path.string() + ".gz", std::ios::binary);
        out.write(reinterpret_cast<char*>(compressed.data()), compressed_size);
        out.close();

        // 更新统计信息
        auto end_time = std::chrono::high_resolution_clock::now();
        stats_.lastOperationTime = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
        stats_.filesCompressed++;
        stats_.bytesSaved += buffer.size() - compressed_size;
        stats_.compressionRatio = 1.0 - (double)compressed_size / buffer.size();

        // 删除原始文件
        std::filesystem::remove(path);
        
        spdlog::get("system")->debug("压缩日志文件: {} (原始大小:{} 压缩后大小:{})", 
            path.filename().string(), buffer.size(), compressed_size);
        return true;
    } catch (const std::exception& e) {
        spdlog::get("error")->error("压缩日志文件失败: {} - {}", path.filename().string(), e.what());
        return false;
    }
}

bool LogManager::healthCheck() const {
    return checkDiskSpace() && 
           stats_.lastOperationTime < std::chrono::seconds(30);
}

double LogManager::getDiskUsage() const {
    auto space = std::filesystem::space("logs");
    return 1.0 - (double)space.available / space.capacity;
}

bool LogManager::checkDiskSpace() const {
    auto space = std::filesystem::space("logs");
    return space.available > 100 * 1024 * 1024; // 至少100MB可用空间
}

void LogManager::enableRemoteLogging(const std::string& host, int port) {
    try {
        syslog_sink_ = std::make_shared<spdlog::sinks::syslog_sink>(
            "hft_system", LOG_PID, LOG_USER, true);
        spdlog::get("system")->sinks().push_back(syslog_sink_);
        spdlog::get("error")->sinks().push_back(syslog_sink_);
        spdlog::get("trade")->sinks().push_back(syslog_sink_);
    } catch (const std::exception& e) {
        spdlog::get("error")->error("远程日志初始化失败: {}", e.what());
    }
}

void LogManager::disableRemoteLogging() {
    if (syslog_sink_) {
        auto remove_sink = [&](auto logger) {
            auto& sinks = logger->sinks();
            sinks.erase(std::remove(sinks.begin(), sinks.end(), syslog_sink_), sinks.end());
        };
        
        remove_sink(spdlog::get("system"));
        remove_sink(spdlog::get("error"));
        remove_sink(spdlog::get("trade"));
        syslog_sink_.reset();
    }
}

void LogManager::addFilter(const std::string& pattern, bool is_regex) {
    try {
        if (is_regex) {
            filters_.emplace_back(std::regex(pattern), true);
        } else {
            filters_.emplace_back(std::regex(".*" + pattern + ".*"), false);
        }
    } catch (const std::exception& e) {
        spdlog::get("error")->error("添加日志过滤器失败: {}", e.what());
    }
}

void LogManager::clearFilters() {
    filters_.clear();
}

void LogManager::rotateByTime() {
    auto now = std::chrono::system_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::hours>(now - last_archive_time_);
    
    bool should_rotate = false;
    switch (rotation_strategy_) {
        case RotationStrategy::HOURLY:
            should_rotate = duration.count() >= 1;
            break;
        case RotationStrategy::DAILY:
            should_rotate = duration.count() >= 24;
            break;
        default:
            break;
    }
    
    if (should_rotate) {
        last_archive_time_ = now;
        // 执行轮转逻辑...
    }
}

void LogManager::setAsyncMode(bool enabled, size_t queue_size, size_t flush_interval_ms) {
    if (enabled) {
        async_pool_ = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
        async_queue_size_ = queue_size;
        spdlog::flush_every(std::chrono::milliseconds(flush_interval_ms));
        
        // 启动监控线程
        monitor_running_ = true;
        monitor_thread_ = std::thread(&LogManager::monitorResources, this);
    } else {
        if (monitor_running_) {
            monitor_running_ = false;
            if (monitor_thread_.joinable()) {
                monitor_thread_.join();
            }
        }
        async_pool_.reset();
    }
}

void LogManager::setLogLevel(const std::string& logger_name, spdlog::level::level_enum level) {
    if (auto logger = spdlog::get(logger_name)) {
        logger->set_level(level);
    }
}

void LogManager::setGlobalLogLevel(spdlog::level::level_enum level) {
    spdlog::set_level(level);
}

bool LogManager::shouldSample() const {
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_real_distribution<> dis(0.0, 1.0);
    
    return dis(gen) <= sampling_rate_;
}

void LogManager::monitorResources() {
    while (monitor_running_) {
        // 模拟获取资源使用情况
        current_queue_size_ = async_pool_ ? async_pool_->queue_size() : 0;
        
        // 如果队列过满，自动降级日志级别
        if (current_queue_size_ > async_queue_size_ * 0.8) {
            setGlobalLogLevel(spdlog::level::warn);
        } else {
            setGlobalLogLevel(spdlog::level::info);
        }
        
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

LogManager::ResourceUsage LogManager::getResourceUsage() const {
    return ResourceUsage {
        .queue_size = current_queue_size_.load(),
        .memory_usage = 0, // 实际实现中需要获取真实内存使用
        .cpu_usage = 0.0  // 实际实现中需要计算CPU使用率
    };
}

void LogManager::cleanOldLogs() {
    try {
        auto now = std::chrono::system_clock::now();
        for (const auto& entry : std::filesystem::recursive_directory_iterator("logs/archive")) {
            if (entry.is_regular_file() && 
                (entry.path().extension() == ".log" || entry.path().extension() == ".gz")) {
                
                auto ftime = std::filesystem::last_write_time(entry);
                auto duration = std::chrono::duration_cast<std::chrono::hours>(
                    now - ftime).count() / 24;
                
                if (duration > retention_days_) {
                    std::filesystem::remove(entry.path());
                    spdlog::get("system")->info("清理旧日志: {} ({}天)", 
                        entry.path().filename().string(), duration);
                }
            }
        }
    } catch (const std::exception& e) {
        spdlog::get("error")->error("日志清理失败: {}", e.what());
    }
}